import { modules, RootState } from './index'
import { CommitOptions, DispatchOptions, Store as VuexStore } from 'vuex' // Store起个别名叫VuexStore

// 获取modules的类型
type Modules = typeof modules

// 获取所有模块下的mutations
type GetMutation<T> = T extends { mutations: infer G } ? G: never
type GetMutations<T> = {
    [K in keyof T]: GetMutation<T[K]>
}
type mutationsObj = GetMutations<Modules>

// 获取所有模块下的actions
type GetAction<T> = T extends { actions: infer G } ? G: never
type GetActions<T> = {
    [K in keyof T]: GetAction<T[K]>
}
type actionsObj = GetActions<Modules>

// 获取所有模块下的getters
type GetGetter<T> = T extends { getters: infer G } ? G: never
type GetGetters<T> = {
    [K in keyof T]: GetGetter<T[K]>
}
type gettersObj = GetGetters<Modules>

// 要组装成这样的格式 =>   tabs/addTabe menu/setCount
type AddPrefix<prefix,keys> = `${prefix & string}/${keys & string}`// & 限制string类型
type Getkey<T,K> = AddPrefix<K, keyof T>
type Getkeys<T> = {
    [K in keyof T]: Getkey<T[K],K>
}[keyof T]

// type ss = Getkeys<mutationsObj>

// 获取当前模块下每个函数的返回值
type GetFunc<T,A,B> = T[A & keyof T][B & keyof T[A & keyof T]]
type GetMethod<T> = {
    [K in Getkeys<T>]:K extends `${infer A}/${infer B}` ? GetFunc<T,A,B>: unknown
}

type GetMutationFunc = GetMethod<mutationsObj>
type GetActionsFunc = GetMethod<actionsObj>
type GetGetterFunc = GetMethod<gettersObj>

export type CommonStore = Omit<VuexStore<RootState>, 'commit' | 'getters' | 'dispatch'> &
{
    // TypeScript通过keyof操作符提取其属性的名称
    // K extends keyof：extends不是继承，是限制K在传进来的mutations里面.比如此例中的addTabs，addCount
    // <M[K]>[1]: 举例addTabs(state:TabsState, tabs: string):void 第一项tabs参数，所以索引是1
    commit<K extends keyof GetMutationFunc,P extends Parameters<GetMutationFunc[K]>[1]>( 
        key: K,
        payload?: P,
        options?: CommitOptions
    ):ReturnType<GetMutationFunc[K]>
}
&
{
    getters:{
        [K in keyof GetGetterFunc]: ReturnType<GetGetterFunc[K]>
    }
}
&
{
    dispatch<K extends keyof GetActionsFunc>(
        key: K,
        payload?: Parameters<GetActionsFunc[K]>[1],
        options?: DispatchOptions
    ):ReturnType<GetActionsFunc[K]>
}
